﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Visuals;
using System.Drawing;
using Silvermoon.Controls.Interfaces;
using Silvermoon.Images;
using Silvermoon.Utils;
using Silvermoon.Controls.Classes;
using Silvermoon.Animations;
using Silvermoon.Core;

namespace Silvermoon.Controls
{
    /// <summary>
    /// Menu Item to be used with <see cref="T:Menu/>.
    /// </summary>
    public class MenuItem : ItemBase, ISelectable
    {
        public readonly int CornerRadius = Control.Scale(10);
        #region fields

        private ImageVisual arrowImage;
        private ImageVisual checkBoxImage;
        private StringVisual visualText;
        private BackgroundVisual background;
        private bool? isChecked;
        private string text;
        private List<Visual> visuals;
        private Menu subMenu;

        #endregion
        #region ctor

        public MenuItem()
            : base()
        {
            visuals = new List<Visual>(3);
            visualText = new StringVisual();
            checkBoxImage = new ImageVisual();
            checkBoxImage.Image = SysImages.Point;
            checkBoxImage.UseTextColor = true;
            checkBoxImage.Visible = false;
            visuals.Add(checkBoxImage);
            visuals.Add(visualText);
            Visuals = visuals;
            Size = new Size(240, 64);
        }


        public override void Dispose()
        {
            if (subMenu != null) subMenu.Dispose();
            if (arrowImage != null) arrowImage.Dispose();
            if (background != null) background.Dispose();
            background = null;
            arrowImage = null;
            Visuals = null;
            base.Dispose();
        }

        #endregion
        #region props

        protected Menu SubMenu
        {
            get
            {
                if (subMenu == null) subMenu = new Menu(Menu);
                return subMenu;
            }
        }

        protected Menu Menu { get { return ListView as Menu; } }

        public bool HasItems { get { return subMenu != null && subMenu.ItemCount > 0; } }

        public bool? Checked { get { return isChecked; } set { if (isChecked != value) { isChecked = value; OnCheckedChanged(); } } }
        public string Text { get { return text ?? string.Empty; } set { if (text != value) { text = value; OnTextChanged(); } } }

        public IList<ItemBase> Items
        {
            get
            {
                return SubMenu.Items;
            }
        }

        public int ItemCount
        {
            get
            {
                return SubMenu.ItemCount;
            }
        }

        #endregion
        #region methods

        protected override void OnLayout()
        {
            visualText.Text = text;
            visualText.Color = Enabled ? Color.Empty : Color.Gray;
            PrepareArrowImage();
            if ((InvalidationMask & (InvalidationFlag.Size | InvalidationFlag.Text)) != 0)
            {
                int textHeight = visualText.TextSize.Height;
                visualText.Bounds = Control.ScaledRect(48, (Height - textHeight) / 2, Width - 48 - 4, textHeight);
            }

            if (Checked.HasValue)
            {
                checkBoxImage.Visible = Checked.Value;
                checkBoxImage.Bounds = Control.ScaledRect(16, (Height - 16) / 2, 16, 16);
            }

            if (IsSelected)
            {
                if (background == null)
                {
                    background = new BackgroundVisual { Colors = ColorUtil.CreateFlatChromeColors(SysColors.HighlightedItemColor), Style = RenderStyle.Chrome };
                    background.Texture = SysImages.Button;
                    InitBackground();
                }
                if (!visuals.Contains(background)) visuals.Insert(0, background);
            }
            else
            {
                visuals.Remove(background);
            }
            TextColor = IsSelected ? SysColors.HighlightedItemTextColor : SysColors.MenuTextColor;

            base.OnLayout();
        }

        private void PrepareArrowImage()
        {
            if (HasItems)
            {
                if (arrowImage == null)
                {
                    arrowImage = new ImageVisual();
                    arrowImage.Image = SysImages.SubItemArrow;
                    arrowImage.Size = new Size(12, 24);
                    arrowImage.Color = Color.Empty;
                    arrowImage.UseTextColor = true;
                }
                if (!visuals.Contains(arrowImage)) visuals.Insert(0, arrowImage);
                arrowImage.Bounds = Control.ScaledRect(Width - 20 - arrowImage.Width, (Height - arrowImage.Height) / 2, arrowImage.Width, arrowImage.Height);
            }
            else
            {
                if (arrowImage != null) visuals.Remove(arrowImage);
            }
        }

        private void InitBackground()
        {
            if (background != null) background.Bounds = Control.Scale(ClientBounds);
        }

        protected virtual void OnCheckedChanged()
        {
            Invalidate(InvalidationFlag.Appearance);
            if (CheckedChanged != null) CheckedChanged(this, EventArgs.Empty);
        }

        protected virtual void OnTextChanged()
        {
            Invalidate(InvalidationFlag.Text);
            if (TextChanged != null) TextChanged(this, EventArgs.Empty);
        }

        public override void OnSelectedChanged()
        {
            base.OnSelectedChanged();
            TextColor = IsSelected ? Color.White : Color.Empty;
        }

        public override void OnMouseUp(MouseUpEventArgs e)
        {
            base.OnMouseUp(e);
            e.AllowDoubleClick = false;
        }

        public override void OnClick()
        {
            if (Enabled)
            {
                if (HasItems)
                {
                    OpenSubMenu();
                }
                else
                {
                    Menu m = Menu;
                    if (m != null) m.Close();
                    base.OnClick();
                }
            }
        }

        public void OpenSubMenu()
        {
            Screen screen = Screen;
            SubMenu.PreLoad();
            Size size = SubMenu.Size;
            if (size.Width < 240) size.Width = 240;
            Rectangle screenBounds = this.ToScreenBounds();
            Rectangle r = new Rectangle(screenBounds.Right, screenBounds.Top, size.Width, size.Height);
            Rectangle menuBounds = Menu.ToScreenBounds();

            if (r.Right > screen.Width) r.X = screen.Width - r.Width;
            if (menuBounds.Left >= r.Left) r.X = menuBounds.Left - r.Width + (screenBounds.Left - menuBounds.Left);
            if (r.Bottom > screen.Height) r.Y = screen.Height - r.Height;
            if (r.X < 0) r.X = 0;
            if (r.Y < 0) r.Y = 0;

            //TransitionMode mode = r.X > screenBounds.X ? TransitionMode.SwipeInFromLeft : TransitionMode.SwipeInFromRight;
            TransitionMode mode = TransitionMode.FadeIn;
            SubMenu.Bounds = r;
            SubMenu.Invalidate(InvalidationFlag.LayoutAppearance);
            SubMenu.Show(mode | TransitionMode.FadeIn);
            SubMenu.FocusItem();
        }

        public MenuItem AddItem(string text)
        {
            return SubMenu.AddItem(text);
        }

        public MenuItem AddItem(string text, bool isChecked)
        {
            return SubMenu.AddItem(text, isChecked);
        }

        public ItemSeparator AddSeparator()
        {
            return SubMenu.AddSeparator();
        }

        #endregion
        #region events

        public event EventHandler CheckedChanged;
        public event EventHandler TextChanged;

        #endregion
    }
}
